﻿#ifndef BASEMODULE_GLOBALHELPER_H
#define BASEMODULE_GLOBALHELPER_H

#include <QString>
#include <QMultiHash>
#include <QPair>
#include <QSharedPointer>
#include <QList>
#include <QStringList>
#include <QIODevice>
#include <QFileInfoList>
#include "API_BaseModule.h"

class QProcess;
class QDomElement;
class QDomDocument;

#define GlobalHelperInstance BaseModule::GlobalHelper::getInstance()

namespace BaseModule
{
    class API_BASEMODULE GlobalHelper : QObject
    {
    public:
        static GlobalHelper* getInstance()
        {
            static GlobalHelper m_instance;
            return &m_instance;
        }

        /// @brief 当前是否在打开项目的过程
        /// @param isOpenProject
        void setIsOpenProject(bool isOpenProject);
        bool getIsOpenProject();

        void setIsPythonRunning(bool isPythonRunning) { m_isPythonRunning = isPythonRunning; };
        bool getIsPythonRunning() {return m_isPythonRunning;};

        /// @brief 获取时间戳
        /// @return 
        qint64 getTimestamp();

        /// @brief 获取时间戳字符串
        /// @return 
        QString getTimestampString();

        /// @brief 发送消息到父进程
        void sendMsgToParentProcess(QString msg);

        /// @brief 字符串转宽字符串
        /// @param data 
        /// @return 
        std::wstring stringToWString(const std::string data);

        /// @brief 通过名称获取进程id
        qint64 getProcessIdByName(std::string processName);

        /// @brief 通过进程id关闭进程
        /// @param processId 
        void closeProcessByProcessId(qint64 processId);

        /// @brief 将 QString ,QString QList拼接为QString
        static QString convertQStringQStringQListToQString(const QList<QPair<QString, QString>>& data);

        /// @brief 将char*解析为 QString,QString QList
        static QList<QPair<QString, QString>> convertStringToQStringQStringQList(QString data);

        /// @brief 将 QPair int int QList拼接为QString , python接口相关
        static QString convertPairIntIntListToQString(QList<QPair<int, QList<int>>> data);

        /// @brief 将char*解析为 QPair int int QList , python接口相关
        static QList<QPair<int, QList<int>>> convertStringToPairIntIntList(char* data);


        /// @brief 将 int, int QMultiHash拼接为QString , python接口相关
        static QString convertIntIntHashToQString(QMultiHash<int, int> data);

        /// @brief 将char*解析为 int, int QMultiHash , python接口相关
        static QMultiHash<int, int> convertStringToIntIntHash(char* data);

        /// @brief 将char*解析为 int, int QMultiHash , python接口相关
        static QMultiHash<int, int> convertStringToIntIntHash(QString data);

        /// @brief 将 int, int QList拼接为QString , python接口相关
        static QString convertIntIntQListToQString(const QList<QPair<int, int>>& data);

        /// @brief 将char*解析为 int, int QList , python接口相关
        static QList<QPair<int, int>> convertStringToIntIntQList(char* data);

        /// @brief 将char*解析为 int, int QList , python接口相关
        static QList<QPair<int, int>> convertStringToIntIntQList(QString data);

        /// @brief 将 QString, double QList拼接为QString , python接口相关
        static QString convertQStringDoubleQPairToQString(const QPair<QString, double>& data);

        /// @brief 将char*解析为 QString, double QList , python接口相关
        static QPair<QString, double> convertStringToQStringDoublePair(QString data);

        /// @brief 将 int ,QString QList拼接为QString , python接口相关
        static QString convertIntQStringQListToQString(const QList<QPair<int, QString>>& data);

        /// @brief 将QList<QList<int>> 拼接为QString
        static QString convertQListQListIntToQString(const QList<QList<int>>& data);

        /// @brief 将QString转为QList<QList<int>> 
        static QList<QList<int>> convertQStringToQListQListInt(const QString& data);


        /// @brief 将char*解析为 int,QString QList , python接口相关
        static QList<QPair<int, QString>> convertStringToIntQStringQList(QString data);

        /// @brief 将 double QList拼接为QString , python接口相关
        static QString convertDoubleListToQString(QList<double> data);

        /// @brief 将char*解析为 double QList , python接口相关
        static QList<double> convertStringToDoubleList(char* data);

        /// @brief 将char*解析为 double QList , python接口相关
        static QList<double> convertStringToDoubleList(QString data);

        /// @brief 将 int QList拼接为QString , python接口相关
        static QString convertIntListToQString(QList<int> data);

        /// @brief 将char*解析为 int QList , python接口相关
        static QList<int> convertStringToIntList(char* data);

        /// @brief 将char*解析为 int QList , python接口相关
        static QList<int> convertStringToIntList(QString data);

        /// @brief 将 QList<QString>转为一个QString,中间用separator隔开,注意separator不应在单个QString中有包含
        /// @param data 待转换数据
        /// @param separator 分隔符
        /// @return 结果
        static QString converQListQStringToQStrng(const QList<QString>& data, const QString& separator);

        /// @brief 用分隔符separator将QStrng转为QList<QString>
        /// @param data 待分割数据
        /// @param separator 分隔符
        /// @return 结果
        static QList<QString> converQStrngToQListQString(const QString& data, const QString& separator);

        /// @brief 将字符串转为QString_int字典
        /// @param input 输入
        /// @param output 输出
        /// @return 是否转换成功
        static bool convertQStringToIntQStringMap(QMap<int, QString>& output, const QString& input);

        /// @brief 将QString_int字典转换为字符串
        /// @param input 输入
        /// @param output 输出
        /// @return 是否转换成功
        static bool convertIntQStringMapToQString(QString& output, const QMap<int, QString>& input);

        //QHash<QString, int>转为QString
        static QString convertQHashQStringIntToQString(const QHash<QString, int>& data);

        //QString转为QHash<QString, int>
        static QHash<QString, int> convertQStringToQHashQStringInt(const QString& data);

        //QList<std::tuple<int, int, QString>>转QString
        static QString convertQListTupleToIntIntQStringToQString(const QList<std::tuple<int, int, QString>>& data);

        //QString转QList<std::tuple<int, int, QString>>
        static QList<std::tuple<int, int, QString>> convertQStringToQListTupleToIntIntQString(const QString& data);

        //std::tuple<int, int, QString>转Qstring
        static QString convertTupleToIntIntQStringToQString(const std::tuple<int, int, QString>& data);

        //QString转std::tuple<int, int, QString>
        static std::tuple<int, int, QString> convertQStringToTupleToIntIntQString(const QString& data);

        //QPair<QString, QVector<double>>转QString
        static QString convertQPairQStringQVectorDoubleToQString(const QPair<QString, QVector<double>>& data);

        //QString转QPair<QString, QVector<double>>
        static QPair<QString, QVector<double>> convertQStringToQPairQStringQVectorDouble(const QString& data);

        //QVector<double>转QString
        static QString convertQVectorDoubleToQString(const QVector<double>& data);

        //QString转QVector<double>
        static QVector<double> convertQStringToQVectorDouble(const QString& data);

        //QList<double>转QString
        static QString convertQListDoubleToQString(const QList<double>& data);

        //QString转QList<double>
        static QList<double> convertQStringToQListDouble(const QString& data);

        //QVector<std::array<QVector<double>, 3>>
        static QString convertQVectorArrayQVectorDoubleToQString(const QVector<std::array<QVector<double>, 3>>& data);

        //QString转QVector<std::array<QVector<double>, 3>>
        static QVector<std::array<QVector<double>, 3>> convertQStringToQVectorArrayQVectorDouble(const QString& data);

        //QVector<QVector<double>>转QString
        static QString convertQVectorQVectorDoubleToQString(const QVector<QVector<double>>& data);

        //QString转QVector<QVector<double>>
        static QVector<QVector<double>> convertQStringToQVectorQVectorDouble(const QString& data);

        // 将QVector<QPair<QPointF, int>>转换为QString
        static QString convertVectorPairQPointFIntToQString(const QVector<QPair<QPointF, int>>& vector);

        // 将QString转换回QVector<QPair<QPointF, int>>
        static QVector<QPair<QPointF, int>> convertQStringToVectorPairQPointFInt(const QString& str);

        //QHash<int, QStringList>转QString
        static QString convertQHashIntQStringListToQString(const QHash<int, QStringList>& data);

        //QString转QHash<int, QStringList>
        static QHash<int, QStringList> convertQStringToQHashIntQStringList(const QString& data);

        //QMultiHash<int, QString>转QString
        static QString convertQMultiHashIntQStringToQString(const QMultiHash<int, QString>& data);

        //QString转QMultiHash<int, QString>
        static QMultiHash<int, QString> convertQStringToQMultiHashIntQString(const QString& data);

        void createDomElement(QDomDocument* doc, QDomElement* rootElement, QString subElementName, QString subElementDomText);

        /// @brief 以只读的方式读取文件
        /// @param filePath 文件路径
        /// @param jsonString 文件中的内容
        /// @return true-成功，false-失败
        bool readFile(QString filePath, QByteArray& jsonString);

        /// @brief 以覆盖的方式写入文件
        /// @param filePath 文件路径
        /// @param jsonString 需要写入的内容
        /// @param openModel 文件的打开模式
        /// @return true-成功，false-失败
        bool writeFile(QString filePath, QByteArray jsonString, QIODevice::OpenMode openModel = QIODevice::WriteOnly | QIODevice::Truncate);

        /// @brief 获取软件安装目录
        /// @return 安装目录
        QString getAppInstallDir();

        /// @brief 初始化项目临时目录
        void GlobalHelper::initProjectTempDir(bool isFromReport);

        /// @brief 获取项目历史目录（存放项目文件）
        QString getProjectTempIODir();

        /// @brief 获取项目临时文件路径（保存项目时临时文件目录，用于存放文件）
        /// @return 项目临时文件路径
        QString getProjectTempFilePath();

        /// @brief 获取记录脚本的文件路径
        /// @return 记录脚本的文件路径
        QString getRecordScriptFilePath();

        /// @brief 获取用户临时目录“C:\Users\Administrator\AppData\Local\Temp”
        /// @return 用户临时目录，QPair<正斜杠路径/，反斜杠路径\\>
        QPair<std::string, std::string> getUserTempPath();

        /// @brief 判断名字是否合法，不含特殊字符、不是空的、长度适合
        /// @param name 名字
        /// @return 是否合法
        bool isLegalName(QString& name);

        /// @brief 获取线宽数组
        /// @return 
        QStringList getLineWidthList();

        /// @brief 获取字体大小数组
        /// @return 
        QStringList getFontSizeList();

        /// @brief 设置文件的修改时间和访问时间
        /// @param filePath 文件完整路径
        void setFileTimes(const QString& filePath);

        /// @brief 创建项目临时目录
        /// @param projectFilePath 项目文件路径
        static bool createProjectTempDir(QString projectFilePath);
        static bool deleteProjectTempDir();

        /// @brief 通过文件路径获取文件名
        /// @param filePath 文件路径
        /// @return 文件名
        static QString getFileNameByFilePath(QString filePath);

        /// @brief 设置仿真数据文件路径
        /// @param filePath 
        void setSimulationDataFilePath(const QString& filePath);

        /// @brief 创建仿真数据临时存放目录
        /// @return 
        bool createSimulationDataTempDir();
        QString getSimulationDataTempDir();

        /// @brief 创建导入数据临时目录
        void createImportDataTempDir();

        /// @brief 获取导入数据临时存放目录
        /// @return 
        QString getImportDataTempDir();

        /// @brief 获取仿真数据文件路径
        /// @return 
        QString getSimulationDataFilePath();

        /// @brief 复制文件夹
        bool copyFolder(const QString& fromDir, const QString& toDir, bool coverFileIfExist);

        /// @brief 设置是否需要弹出窗口 打开项目时关闭各类弹窗
        /// @param isNeedPopupWindow 
        void setIsNeedPopupWindow(bool isNeedPopupWindow);
        /// @brief 是否需要弹窗 打开项目时关闭各类弹窗
        /// @return 
        bool getIsNeedPopupWindow();
        // @brief 创建临时目录tempIO，此功能会清空之前的所有文件，谨慎调用
        /// @return 创建结果
        bool createTempDir();

        /// @brief 当前安装目录的路径转换
        /// @param path 模型文件路径/parser路径等
        /// @return 是否转换成功
        bool CurrentInstallationDirectoryPathConversion(QString& path);

        bool isDoubleValueInRange(double value, double min, double max);

        QString autoIncreaseName(QSet<QString>& names, QString name);

        QString hashToBase64(const QHash<int, QStringList>& map);

        QHash<int, QStringList> base64ToHash(const QString& base64Str);

        QString hashToJsonString(const QHash<QString, QString>& hash);

        QHash<QString, QString> jsonStringToHash(const QString& json);

    private:
        /// @brief 判断是否能创建项目临时目录
        /// @param projectFilePath 项目文件路径
        /// @return 查询结果
        static bool canCreateProjectTempDir(QString projectFilePath);

    private:
        /// @brief 项目名
        static QString m_projectName;
        /// @brief 软件的安装目录
        QString m_installDir;
        /// @brief 临时目录
        static QString m_tempIODir;
        /// @brief 记录脚本的文件路径
        QString m_recordScriptFilePath;

        //仿真数据临时目录，在打开仿真数据时创建，在保存项目时放到项目目录
        QString m_simulationDataFilePath{""};
        /// @brief 打开的仿真数据文件存放路径
        QString m_simulationDataTempFileDir{""};
        /// @brief 导入数据的文件存放路径
        QString m_ImportDataTempFileDir{""};

        bool m_isNeedPopupWindow{true};

        bool m_isOpenProject{false};

        bool m_isPythonRunning{false};
    };
}
#endif // GLOBALHELPER_H
